// ------------------------------------------------------------------------------------------------
// File   : DX9HeadLight.cpp
// Date   : 2011-07-30
// Author : Weng xiao yi
// Descr. : Create an Post process HeadLight Circle Ring Effect of the frame buffer and cover the back buffer
//
// ------------------------------------------------------------------------------------------------

// ------------------------------------------------------------------------------------------------
// HEADERS
// ------------------------------------------------------------------------------------------------
#include <engine_stdafx.h>
// ------------------------------------------------------------------------------------------------
// IMPLEMENTATION
// ------------------------------------------------------------------------------------------------
DX9AE_HeadLight::DX9AE_HeadLight()
: DX9AfterEffect()
{
	SetAllResourceNull();
}

DX9AE_HeadLight::~DX9AE_HeadLight()
{
	Shutdown();
}

void DX9AE_HeadLight::SetAllResourceNull()
{
	m_afFactor[eDX9_AE_HeadLight_Param_CircleCenter_X] = 0;
	m_afFactor[eDX9_AE_HeadLight_Param_CircleCenter_Y] = 0;
	m_afFactor[eDX9_AE_HeadLight_Param_CircleCenter_Z] = 0;
}

void DX9AE_HeadLight::ReInit()
{
	SetAllResourceNull();
}

void DX9AE_HeadLight::OnDeviceLost()
{
	Shutdown();

	DX9AfterEffect::OnDeviceLost();
}

void DX9AE_HeadLight::OnDeviceReset()
{
	DX9AfterEffect::OnDeviceReset();

	ReInit();
}

void DX9AE_HeadLight::Shutdown()
{

}

void DX9AE_HeadLight::Apply()
{	
	HRESULT hr;

	IHRTexture* pHLTexture = GetHREngine()->GetTextureMgr()->GetTexture( CHeadLightMgr::GetInstance().GetMapHeadLightTexID() );
	if( !pHLTexture )
		return;

	IHRRenderer* RI = GetHREngine()->GetRenderer();
	LPDIRECT3DDEVICE9 pD3DDev = (LPDIRECT3DDEVICE9)(RI->GetRealDevice());
	ICubeMaterial::MaterialList &Mat_list = ICubeMaterial::GetInstance().GetMaterialList();
	const ICubeMaterial::MaterialInfo &PostMaterial_info = Mat_list[ICubeMaterial::eMaterial_posteffect];
	ICubeMaterial::MaterialInfo *pHeadLightMaterial = new ICubeMaterial::MaterialInfo();
	pHeadLightMaterial->CloneMaterial(PostMaterial_info);
	pHeadLightMaterial->m_bSkipSetting = false;
	pHeadLightMaterial->m_bSkipPostRender = false;
	pHeadLightMaterial->m_material->GetRenderPass(0)->AddForcedProperty( &S_SamplerStateProperty_1_U_CLAMP);
	pHeadLightMaterial->m_material->GetRenderPass(0)->AddForcedProperty( &S_SamplerStateProperty_1_V_CLAMP);
	pHeadLightMaterial->m_material->GetRenderPass(0)->AddForcedProperty( &S_SamplerStateProperty_1_MIN_LINEAR);
	pHeadLightMaterial->m_material->GetRenderPass(0)->AddForcedProperty( &S_SamplerStateProperty_1_MAG_LINEAR);


	GetSceneEffect()->StretchBackBufferToDecolor();

	GetCubeMaterialRenderer()->PushMaterial( pHeadLightMaterial->m_material, MM_Add );
	GetCubeMaterialRenderer()->ComputeMaterialPass();
	GetCubeMaterialRenderer()->OnePassPreRenderMaterial( 0 );

	// get vertex shader for this material
	DX9VertexShaderManager::DX9VSFeatureAfterEffect oVSFeature;
	oVSFeature.stKey.ulShaderVer	 = 20;
	oVSFeature.stKey.ulEffectId      = AE_TYPE_HeadLight;
	oVSFeature.stKey.ulEffectSubType = 0;
	DX9VertexShader* pVertexShader = DX9GetVertexShaderManager()->GetShader(&oVSFeature);

	// get pixel shader for this material
	DX9PixelShaderManager::DX9PSFeatureAfterEffect oPSFeature;
	oPSFeature.stKey.ulShaderVer	 = 20;
	oPSFeature.stKey.ulEffectId      = AE_TYPE_HeadLight;
	oPSFeature.stKey.ulEffectSubType = 0;
	DX9PixelShader* pPixelShader = DX9GetPixelShaderManager()->GetShader(&oPSFeature);

	// use shaders
	hr = pD3DDev->SetVertexShader(pVertexShader->GetShaderInterface());
	DX9Verify( SUCCEEDED(hr) );
	hr = pD3DDev->SetPixelShader(pPixelShader->GetShaderInterface());
	DX9Verify( SUCCEEDED(hr) );

	pD3DDev->SetTexture( 0, GetSceneEffect()->GetDecolorTexture() );
	pD3DDev->SetTexture( 1, (LPDIRECT3DTEXTURE9)(pHLTexture->GetData()) );

	VECTOR4FLOAT vScreenResolution;
	vScreenResolution.x = GetHR3DConfig()->GetScreenWidth();
	vScreenResolution.y = GetHR3DConfig()->GetScreenHeight();
	vScreenResolution.z = 0.5f / GetHR3DConfig()->GetScreenWidth();
	vScreenResolution.w = 0.5f / GetHR3DConfig()->GetScreenHeight();

	// upload constants
	if (pVertexShader->IsGlobalConstPresent( VS_GLOBAL_CONSTANT_SCREEN_RESOLUTION))
		pVertexShader->SetGlobalVector( VS_GLOBAL_CONSTANT_SCREEN_RESOLUTION, &vScreenResolution );
	
	VECTOR4FLOAT vCircleCenter = { m_afFactor[eDX9_AE_HeadLight_Param_CircleCenter_X],
								   m_afFactor[eDX9_AE_HeadLight_Param_CircleCenter_Y],
								   m_afFactor[eDX9_AE_HeadLight_Param_CircleCenter_Z],
								   1.0f };
	if (pVertexShader->IsGlobalConstPresent(VS_GLOBAL_CONSTANT_CIRCLECENTER))
		pVertexShader->SetGlobalVector(VS_GLOBAL_CONSTANT_CIRCLECENTER, &vCircleCenter);

	if (pVertexShader->IsGlobalConstPresent(VS_GLOBAL_CONSTANT_WORLDVIEWPROJ))
		pVertexShader->SetGlobalMatrix(VS_GLOBAL_CONSTANT_WORLDVIEWPROJ, &GetHR3DConfig()->GetCamera()->GetViewXProj());

	VECTOR4FLOAT vCircleTexScale = {0, 0, 0, 0};
	D3DXVECTOR3 ViewVec3 = GetHR3DConfig()->GetCamera()->GetEyePt() - GetHR3DConfig()->GetCamera()->GetLookatPt();
	vCircleTexScale.x = D3DXVec3Length( &ViewVec3 ) / 40.0f;
	if (pVertexShader->IsGlobalConstPresent(VS_GLOBAL_CONSTANT_CIRCLETEXSCALE))
		pVertexShader->SetGlobalVector(VS_GLOBAL_CONSTANT_CIRCLETEXSCALE, &vCircleTexScale);



	RI->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 2 );


	pD3DDev->SetVertexShader(NULL);
	pD3DDev->SetPixelShader(NULL);
	pD3DDev->SetTexture( 0, NULL );
	pD3DDev->SetTexture( 1, NULL );

	GetCubeMaterialRenderer()->OnePassPostRenderMaterial( 0 );
	GetCubeMaterialRenderer()->PopMaterial();

	if( pHeadLightMaterial->m_material )
		delete pHeadLightMaterial->m_material;
	pHeadLightMaterial->m_material = NULL;
	delete pHeadLightMaterial;
	pHeadLightMaterial = NULL;
}
